using System.Collections.Generic;
using JufGame.MathHelper;
using UnityEngine;

namespace JufGame
{
	/// <summary>
	/// 特征解决方案
	/// </summary>
	[System.Serializable]
	public class FeatureSolution
	{
		[SerializeField] private Vector4 totalCost;
		[SerializeField] private Vector3 totalAudacity;
		[SerializeField] private int onlyID;
		[SerializeField] private FeatureEnum[] features;
		[SerializeField] private AI_LOD[] configs;
		private readonly Dictionary<FeatureEnum, AI_LOD> solution = new();
		private readonly List<SolutionTrans> upgradeTransitions = new();
		private readonly List<SolutionTrans> downgradeTransitions = new();
		private Vector3 minUpgradeW = Vector3.one * float.MaxValue;
		private Vector3 maxDowngradeW = Vector3.one * float.MinValue;
		private Matrix upgradeMatrix;
		private Matrix downgradeMatrix;
		/// <summary>
		/// 比较s1是否等同于s2
		/// </summary>
		public static bool IsSameID(FeatureSolution s1, FeatureSolution s2)
		{
			return s1.onlyID == s2.onlyID;
		}
		/// <summary>
		/// 获取当前方案下指定特征的LOD
		/// </summary>
		/// <param name="feature">试查询LOD的特征</param>
		/// <returns>特征的LOD</returns>
		public AI_LOD GetLODForFeatureEnum(FeatureEnum feature)
		{
			if(solution.TryGetValue(feature, out AI_LOD lod))
			{
				return lod;
			}
			return AI_LOD.Lowest;
		}
		/// <summary>
		/// 获取已预处理过的转换列表
		/// </summary>
		/// <param name="transType">转换类型</param>
		public List<SolutionTrans> GetTransitions(TransType transType)
		{
            return transType switch
            {
                TransType.Upgrade => upgradeTransitions,
                TransType.Downgrade => downgradeTransitions,
                _ => null,
            };
        }
		/// <summary>
		/// 获取已预处理过的W转换矩阵
		/// </summary>
		/// <param name="transType">转换类型</param>
		public Matrix GetWMatrix(TransType transType)
		{
			return transType switch
			{
				TransType.Upgrade => upgradeMatrix,
				TransType.Downgrade => downgradeMatrix,
				_ => null,
			};
		}
		/// <summary>
		/// 初始化解决方案的特征配置，为每个特征绑定对应的LOD
		/// </summary>
		public void InitSolution()
		{
			for(int i = 0; i < features.Length; ++i)
			{
				solution.Add(features[i], configs[i]);
			}
		}
		/// <summary>
		/// 添加新的特征解决方案到升、降级列表
		/// </summary>
		/// <param name="other">其他特征解决方案</param>
		/// <param name="limitResMul">最低的资源因子向量</param>
		public void InitTranstions(FeatureSolution other, Vector4 limitResMul, List<Vector3> upgradeWs, List<Vector3> downgradeWs)
		{
			var relAudacity = other.totalAudacity - totalAudacity;
			var relCost = other.totalCost - totalCost;
			var isDecsLOD = relAudacity.AllGreaterEquel(0);
			var isIncrCost = relCost.AllGreaterEquel(0); 
			if (isDecsLOD && isIncrCost)//如果LOD下降但费用还会增加，则舍弃
			{
				return;
			}
			var costVal = Vector4.Dot(limitResMul, relCost);
			var w = relAudacity / costVal;
			if(w.AllGreaterEquel(0))
			{
				if (costVal < 0)
				{
					var trans = new SolutionTrans(other, relAudacity, relCost);
					upgradeTransitions.Add(trans);
				}
				else return;
			}
			else
			{
				w *= -1;//转为正数
				if(isDecsLOD && relCost.AllLessEquel(0))
				{
					if(w.x >= maxDowngradeW.x && w.y >= maxDowngradeW.y && w.z >= maxDowngradeW.z)
					{
						maxDowngradeW = w;
					}
					downgradeWs.Add(w);
					var trans = new SolutionTrans(other, relAudacity, -relCost);
					downgradeTransitions.Add(trans);
				}
				else 
				{
					if(w.x <= minUpgradeW.x && w.y <= minUpgradeW.y && w.z <= minUpgradeW.z)
					{
						minUpgradeW = w;
					}
					upgradeWs.Add(w);
					var trans = new SolutionTrans(other, -relAudacity, relCost.Abs());
					upgradeTransitions.Add(trans);
				}
			}
		}
		/// <summary>
		/// 初始化升级、降级矩阵，确保升降级转化表已初始化
		/// </summary>
		public void InitWMatrixs(List<Vector3> upgradeWs, List<Vector3> downgradeWs)
		{
			int realColumns = 0;
			upgradeMatrix = new Matrix(3, upgradeWs.Count);
			downgradeMatrix = new Matrix(3, downgradeWs.Count);
			for(int i = 0; i < upgradeWs.Count; ++i)
			{
				if(upgradeWs[i] != minUpgradeW)
				{
					upgradeMatrix[0, realColumns] = upgradeWs[i].x;
					upgradeMatrix[1, realColumns] = upgradeWs[i].y;
					upgradeMatrix[2, realColumns] = upgradeWs[i].z;
					realColumns++;
				}
			}
			upgradeMatrix.SetColums(realColumns);
			realColumns = 0;
			for(int i = 0; i < downgradeWs.Count; ++i)
			{
				if(downgradeWs[i] != maxDowngradeW)
				{
					downgradeMatrix[0, realColumns] = downgradeWs[i].x;
					downgradeMatrix[1, realColumns] = downgradeWs[i].y;
					downgradeMatrix[2, realColumns] = downgradeWs[i].z;
					realColumns++;
				}
			}
			downgradeMatrix.SetColums(realColumns);
		}

		#region 仅在Unity编辑时使用
		#if UNITY_EDITOR
		public int OnlyID { get => onlyID; set{ onlyID = value; }}
		public Vector4 TotalCost => totalCost;
		public Dictionary<LOD_Feature, int> FeatureConfigs => featureConfigs;
		private readonly Dictionary<LOD_Feature, int> featureConfigs;
		public FeatureSolution()
		{
			featureConfigs = new Dictionary<LOD_Feature, int>();
		}
		public FeatureSolution(FeatureSolution solution)
		{
			featureConfigs = new Dictionary<LOD_Feature, int>(solution.featureConfigs);
		}
		/// <summary>
		/// 获取指定特征的LOD
		/// </summary>
		public AI_LOD GetLODForFeature(LOD_Feature feature)
		{
			return feature.Configs[featureConfigs[feature]].LOD;
		}
		/// <summary>
		/// 增加特征转换元素
		/// </summary>
		/// <param name="newfeature">新的特征</param>
		/// <param name="configIndex">转换需要的lOD在其lOD集合中的下标</param>
		public void AddChoice(LOD_Feature newfeature, int configIndex)
		{
			featureConfigs.Add(newfeature, configIndex);
		}
		/// <summary>
		/// 复制一份该特征方案
		/// </summary>
		public FeatureSolution Clone()
		{
			return new FeatureSolution(this);
		}
		/// <summary>
		/// 获取当前方案下的所有特征
		/// </summary>
		/// <returns>所有的特征</returns>
		public HashSet<LOD_Feature> GetAllFeatures()
		{
			var allFeatures = new HashSet<LOD_Feature>();
			foreach(var f in featureConfigs)
			{
				allFeatures.Add(f.Key);
			}
			return allFeatures;
		}
		/// <summary>
		/// 计算该特征方案的总体数据(总耗费、总鲁莽度)
		/// </summary>
		public void CalcTotalDatas()
		{
			totalCost = Vector4.zero;
			totalAudacity = Vector3.zero;
			foreach(var f in featureConfigs)
			{
				totalCost += f.Key.Configs[f.Value].Cost;
				totalAudacity += f.Key.Configs[f.Value].AudacityVector;
			}
		}
		/// <summary>
		/// 特征方案初始化后，保留有效信息
		/// </summary>
		public void FinishInit()
		{
			var featureCount = featureConfigs.Count;
			int i = 0;
			features = new FeatureEnum[featureCount];
			configs = new AI_LOD[featureCount];
			foreach(var s in featureConfigs)
			{
				features[i] = s.Key.E_Feature;
				configs[i] = s.Key.Configs[s.Value].LOD;
				++i;
			}
		}
		#endif
		#endregion
    }
}
